package com.andy.buyu.server.game;

import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.andy.buyu.server.entity.ConfFish;
import com.andy.buyu.server.entity.ConfScript;
import com.andy.buyu.server.entity.ConfStag;
import com.andy.buyu.server.game.task.TimerManager;
import com.andy.buyu.server.socket.SendUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class FishGame implements Serializable{

	private static final long serialVersionUID = 1L;
	
	private static Logger logger = LoggerFactory.getLogger(FishGame.class);
	
	public static AtomicInteger counter = new AtomicInteger();
	
	private int id = counter.incrementAndGet();

	private int status;
	
	private Room room;
	
	private long startTime;
	
	private long pauseTime; // 暂停时间
	
	private ScheduledFuture<?> againSch; // 重新开始计时器
	
	private int times; // 重复第几轮
	
	private ConfStag confStag;
	// 被捕获的鱼key:scriptId
	private Set<Integer> catchedFishs;
	
	private boolean isBossDead;
	
	public FishGame(Room room) {
		this.room = (room);
		start();
	}
	
	public int getId() {
		return id;
	}
	
	public void start() {
		// 加载剧本
		if(confStag != null && confStag.getNextStage() != null && confStag.getNextStage() != 0) {
			// 连续场景
			confStag = GameConf.getStageById(confStag.getNextStage());
		} else {
			// 初始场景
			long sysCoin = Global.sysCurrHave.get();
			confStag = GameConf.getStage(sysCoin);
		}
		if(logger.isInfoEnabled()){
			logger.info("加载剧本：{}-{}",confStag.getStagId(),confStag.getScriptId());
		}
		
		catchedFishs = Sets.newConcurrentHashSet();
		times++;
		startTime = System.currentTimeMillis();
		status = 0;
		initTask(0);
	}

	/**
	 * 初始化定时器
	 * @param playTime 已玩时间
	 */
	private void initTask(long playTime) {
		// 鱼类定时进入场景
//		confStag.scripts().forEach((script)->{
//			TimerManager.schedule(()->{
//				if(!isEnd()) {
//					enterFish(script);
//				}
//				return null;
//			}, script.getShowTime());
//		});
		// 最后一条鱼结束决定游戏是否重新开始
		List<ConfScript> scripts = confStag.scripts();
		ConfScript lastScript = scripts.get(scripts.size()-1);
		long delay = lastScript.getOutTime()-playTime;
		if(delay < 0)delay = 10;
		againSch = TimerManager.schedule(()->{
			if(!isEnd()) {
				restart();
			}
			return null;
		}, delay);
	}
	
	private void restart() {
		synchronized (this) {
			// 播放过场动画后开始游戏
			start();
		}
		// 发送剧本开始包
		SendUtil.send205(room,this);
		
	}

//	public void gameOver() {
//		end();
//		this.room = null;
//	}
	
	public void gamePause() {
		logger.info("游戏暂停：{}",id,startTime);
		synchronized (this) {
			end();
			pauseTime = System.currentTimeMillis();
			if(againSch != null) {
				againSch.cancel(false);
				againSch = null;
			}
		}
	}
	
	/**
	 * 继续
	 */
	public void continun() {
		logger.info("游戏继续：{}-{}",id,pauseTime);
		status = 0;
		if(pauseTime > 0) {
			long playTime = pauseTime - startTime;
			startTime = startTime+(System.currentTimeMillis() - pauseTime);
			initTask(playTime);
		}
	}

	public void enterFish(ConfScript script){
//		fishs.put(script.getScriptId(),System.currentTimeMillis());
//		SendUtil.send201(room, script);
	}
	
	public void outFish(int scriptId, ConfFish fish, int rate){
		catchedFishs.add(scriptId);
		if(fish.getType() == 13 || fish.getType() == 31){
			room.addRank(new Rank(fish.getFishId(),rate));
		}
	}
	
	
	/**
	 * 获取已经捕获的鱼
	 * @return
	 */
	public Set<Integer> getFishs() {
		return catchedFishs;
	}
	
	public int getStageId() {
		return confStag.getStagId();
	}
	
	/**
	 * 该鱼是否可捕获
	 * @param scriptId
	 * @return
	 */
	public boolean checkFish(Integer scriptId){
		if(catchedFishs.contains(scriptId)) return false;
		ConfScript script = GameConf.getScript(scriptId);
		long now = System.currentTimeMillis()-startTime;
		return now >= script.getShowTime() && now <= script.getOutTime();
	}

	public void end(){
		status = -1;
	}
	
	public boolean isEnd(){
		return status == -1;
	}

	public String getMapRes() {
		return confStag.getMapRes();
	}

	public long getStartTime() {
		return startTime;
	}

	public int getTimes() {
		return times;
	}

	/**
	 * 获取在场的所有同种鱼
	 * @param func
	 * @return
	 */
	public List<Integer> getScriptsByFishId(Integer fishId) {
		List<Integer> result = Lists.newArrayList();
		confStag.scripts().forEach((scr)->{
			if(scr.getFishId().equals(fishId)){
				result.add(scr.getScriptId());
			}
		});
		return result;
	}

	/**
	 * 获取在场景里面的所有鱼
	 * @return
	 */
	public List<Integer> getInFishs() {
		List<Integer> result = Lists.newArrayList();
		confStag.scripts().forEach((scr)->{
			if(checkFish(scr.getScriptId())){
				result.add(scr.getScriptId());
			}
		});
		return result;
	}

	public boolean isBossDead() {
		return isBossDead;
	}

	public void setBossDead(boolean isBossDead) {
		this.isBossDead = isBossDead;
	}

	public boolean haveBoss() {
		return confStag.isHaveBoss();
	}

	public boolean isBossShow() {
		for(ConfScript scr:confStag.scripts()){
			ConfFish fish = GameConf.getFish(scr.getFishId());
			if(fish != null && fish.getType() == 31){
				long now = System.currentTimeMillis()-startTime;
				return now >= scr.getShowTime();
			}
		}
		return false;
	}

}
